import 'dart:typed_data';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:toast/toast.dart';
import 'package:weightsmartlightapp/blueUuid.dart';
import 'package:weightsmartlightapp/device_name.dart';
import 'dateTimePicker/date.dart';
import 'dateTimePicker/flutter_my_picker.dart';
import 'dart:async';
import 'package:flutter/foundation.dart';

class SmartLightControllerPage extends StatefulWidget {
  @override
  State createState()=>_SmartLightPageState();
}

class _SmartLightPageState extends State<SmartLightControllerPage> {
  static const platform = const MethodChannel('my.flutter.io/bluetooth'); //定义与底层操作系统的方法调用通道
  static const EventChannel _eventChannelPlugin = EventChannel('my.flutter.event/bluetooth'); //定义接收底层操作系统主动发来的消息通道
  StreamSubscription _streamSubscription; //广播流来处理EventChannel发来的消息

  int _coolLightShowPwm=0;//因为flutter的slider的divisions太大会导致滑动时会出现突然数值保留小数点好多位,所以单独弄一个显示变量来绑定
  int _warmLightShowPwm=0;//因为flutter的slider的divisions太大会导致滑动时会出现突然数值保留小数点好多位,所以单独弄一个显示变量来绑定
  double _coolLightPwm=0.0;//冷灯pwm值
  double _warmLightPwm=0.0;//暖灯pwm值
  bool _absoluteSwitchSelected=true; //维护绝对时间单选开关状态
  bool _relativeSwitchSelected=true; //维护相对时间单选开关状态
  TextEditingController _absoluteTimeTextController = TextEditingController();//绝对时间设置的文本框controller
  TextEditingController _relativeTimeTextController = TextEditingController();//相对时间设置的文本框controller
  DateTime _absoluteDateTime=new DateTime.now();//当前的绝对时间
  String _absoluteDateStr;//当前的绝对时间的字符串表示
  RelativeTimeRecode _relativeTimeRecode=RelativeTimeRecode(0,0,0,0,0,0);//当前的相对时间
  String _relativeDateStr;//当前的相对时间的字符串表示

  //widget初始化之后调用
  void afterBuildCallback(BuildContext context) {
    Future.delayed(Duration(seconds: 2), () {//进入界面两秒之后去校准设备时间
      _correctTime();
    });
  }


  @override
  Widget build(BuildContext context) {
    return new WillPopScope(
        onWillPop: () async {
          //导航回到主界面
          platform.invokeMethod('disConnectDevice',DeviceName.LIGHT_DEVICE_NAME).then((value) {});//调用底层去与蓝牙设备断开连接
          return false;
        },
        child:Scaffold(
          appBar: AppBar(
            title: Text('冷暖灯'),
          ),
          body: Center(
              child: Column(
                children: <Widget>[
                  Expanded(
                    flex: 2,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      //让row布局里的组件平分主轴空间
                      children: <Widget>[
                        RaisedButton(
                          child: Text("开冷灯"),
                          onPressed: () {
                            _directControllerLight(true,1);
                          },
                        ),
                        RaisedButton(
                          child: Text("开暖灯"),
                          onPressed: () {
                            _directControllerLight(true, 2);
                          },
                        ),
                        RaisedButton(
                          child: Text("关灯"),
                          onPressed: () {
                            _directControllerLight(false,0);
                          },
                        )
                      ],
                    ),
                  ),
                  Expanded(
                    flex: 2,
                    child: getPwmBody(true)
                  ),
                  Expanded(
                    flex: 2,
                    child: getPwmBody(false)
                  ),
                  Expanded(
                    flex: 2,
                    child: _getTimerBody(true)
                  ),
                  Expanded(
                    flex: 2,
                    child: _getTimerBody(false)
                  ),
                ],
              )
          ),
        )
    );
  }

  @override
  void initState() {
    //当Widget第一次插入到Widget树时会被调用,并且只会调用一次
    super.initState();
    _streamSubscription = _eventChannelPlugin
        .receiveBroadcastStream()
        .listen(_onToDart, onError: _onToDartError); //注册消息回调函数
    WidgetsBinding.instance.addPostFrameCallback((_) =>
        afterBuildCallback(context)); //注册一个回调函数在widget初始化完成之后调用
  }

  void _onToDart(dynamic message) {
    //底层发送成功消息时会进入到这个函数来接收
    if(message["deviceName"]==DeviceName.LIGHT_DEVICE_NAME){//如果是发给自己的才去处理
      switch(message['code']){
        case '80005'://如果是notify传回来的数据
          Uint8List data=message['data'];
          if(data[1]==0x10)//如果是校准时间的返回
            _showToast('时间校准'+(data[3]==0x01?'成功':'失败'));
          else if(data[1]==0x20){//如果是开关灯的返回结果的话
            switch(data[3]){
              case 0x00://如果是关灯操作
                setState(() {
                  _coolLightShowPwm=0;
                  _coolLightPwm=0.0;
                  _warmLightShowPwm=0;
                  _warmLightPwm=0.0;
                });
                _showToast("关灯"+(data[4]==0x01?'成功':'失败'));
                break;
              case 0x01://如果是开启冷灯操作
                setState(() {
                  _coolLightShowPwm=99;
                  _coolLightPwm=99.0;
                  _warmLightShowPwm=0;
                  _warmLightPwm=0.0;
                });
                _showToast("开启冷灯"+(data[4]==0x01?'成功':'失败'));
                break;
              case 0x02://如果是开启暖灯操作
                setState(() {
                  _warmLightShowPwm=99;
                  _warmLightPwm=99.0;
                  _coolLightShowPwm=0;
                  _coolLightPwm=0.0;
                });
                _showToast("开启暖灯"+(data[4]==0x01?'成功':'失败'));
                break;
            }
          }else if(data[1]==0x40)//如果是调整冷灯pwm返回的结果
            _showToast('冷灯PWM调节'+(data[4]==0x00?'失败':'成功')+',当前为'+data[3].toString());
          else if(data[1]==0x50)//如果是调整暖灯pwm返回的结果
            _showToast('暖灯PWM调节'+(data[4]==0x00?'失败':'成功')+',当前为'+data[3].toString());
          else if(data[1]==0x90)//如果是设置绝对定时开关灯
            _showToast('设置绝对定时开关'+(data[3]==0x00?'失败':'成功'));
          else if(data[1]==0xA0)//如果是设置相对定时开关灯
            _showToast('设置相对定时开关'+(data[3]==0x00?'失败':'成功'));
          break;
        case "80002"://如果连接被手动断开
          print("台灯界面收到连接被手动断开的消息");
          Navigator.popUntil(context, ModalRoute.withName('home'));//就直接回到主界面
          break;
      }
    }
  }

  void _onToDartError(dynamic error) {
    //底层发送错误消息时会进入到这个函数来接收
    if(error.details==DeviceName.LIGHT_DEVICE_NAME){//是发给自己的才去处理
      switch(error.code){
        case "90001"://如果扫描不到目标设备
          print("台灯界面收到扫描不到目标设备的消息");
          Navigator.popUntil(context, ModalRoute.withName('home'));//就直接回到主界面
          break;
        case "90002"://与设备的连接断开
          print("台灯界面收到与设备的连接断开的消息");
          _showToast('与设备的连接断开,现在尝试再去连接设备');
          Map<String,Object> dataMap={
            "deviceName":DeviceName.LIGHT_DEVICE_NAME,
            "uuidDataType":defaultTargetPlatform==TargetPlatform.android?BlueUuid.androidLightUuidType:null,
            "deviceUuid":defaultTargetPlatform==TargetPlatform.android?BlueUuid.androidLightUuid:BlueUuid.iosLightUuid,
            "notify_d":defaultTargetPlatform==TargetPlatform.android?BlueUuid.androidNotify_d:null,
            "notifyUuid":defaultTargetPlatform==TargetPlatform.android?BlueUuid.androidLightNotifyUuid:BlueUuid.iosLightNotifyUuid
          };
          platform.invokeMethod('connectDevice',dataMap).then((value){print(value);});//调用底层去连接蓝牙设备
          break;
      }
    }
  }

  //返回小标题
  Widget getPartTitle(String title){
    return Container(
                child: Text(title),
                alignment: Alignment.center, //组件居中
                color: Colors.blue,
                width: double.infinity, //宽度尽可能大
    );
  }

  //返回pwm的body内容
  Widget getPwmBody(bool isCool){
    return Column(
      children: <Widget>[
        Expanded(
            flex: 3,
            child:getPartTitle(isCool?'冷灯PWM调节':'暖灯PWM调节')
        ),
        Expanded(
          flex: 7,
          child: Row(
            children: <Widget>[
              Expanded(
                flex: 5,
                child: Text('当前值:'+(isCool?'$_coolLightShowPwm':'$_warmLightShowPwm'),textAlign: TextAlign.center,style: TextStyle(fontSize: 18.0)),
              ),
              Expanded(
                  flex: 5,
                  child: Slider(
                      value: isCool?_coolLightPwm:_warmLightPwm,
                      onChanged: (double data){
                          if(isCool){
                            setState(() {
                              _coolLightShowPwm=data.floor();
                              _coolLightPwm = data;
                            });
                          }else{
                            setState(() {
                              _warmLightShowPwm=data.floor();
                              _warmLightPwm = data;
                            });
                          }
                          _pwmSliderChange(isCool);
                      },
                      min: 0.0,
                      max: 99.0,
                      divisions: 100,
                      label: isCool?'$_coolLightShowPwm':'$_warmLightShowPwm',
                      activeColor: Colors.green,
                      inactiveColor: Colors.grey
                  )
              )
            ],
          ),
        )
      ],
    );
  }

  //返回定时设置的body
  Widget _getTimerBody(bool isAbsolute){
    return Column(
      children: <Widget>[
        Expanded(
          flex: 3,
          child:getPartTitle(isAbsolute?'绝对时间设置':'相对时间设置'),
        ),
        Expanded(
          flex: 7,
          child: Row(
            children: <Widget>[
              Expanded(
                flex: 5,
                child: TextField(
                  controller: isAbsolute ? _absoluteTimeTextController : _relativeTimeTextController,
                  maxLines:null,//时间字符串太长了，所以一定要换行显示
                  onTap: () {//点击事件
                    _showDatePicker(isAbsolute);//显示dataTimePicker
                  },
                  readOnly: true,//防止键盘弹出
                  decoration: InputDecoration(
                      labelText: "时间",
                      hintText: "选择时间",
                      prefixIcon: Icon(Icons.timer)
                  ),
                ),
              ),
              Expanded(
                  flex: 5,
                  child: Row(
                    children: <Widget>[
                      Switch(
                        value: isAbsolute ? _absoluteSwitchSelected : _relativeSwitchSelected,//当前状态
                        onChanged:(value){
                          //重新构建页面
                          setState(() {
                            if(isAbsolute)
                              _absoluteSwitchSelected=value;
                            else
                              _relativeSwitchSelected=value;
                          });
                        },
                      ),
                      RaisedButton(
                        child: Text("设置"),
                        onPressed: () {
                          _timerSetting(isAbsolute);
                        },
                      )
                    ],
                  )
              )
            ],
          ),
        )
      ],
    );
  }

  //对设备进行时间校准
  void _correctTime(){
    print('现在去校准设备时间');
    DateTime now=DateTime.now();
    Uint8List data = new Uint8List(10);
    data[0]=0xFE;
    data[1]=0xD0;
    data[2]=0x07;
    data[3]=now.year-2000;
    data[4]=now.month;
    data[5]=now.day;
    data[6]=now.hour;
    data[7]=now.minute;
    data[8]=now.second;
    data[9]=now.weekday;
    Map<String,Object> dataMap={"data":data};
    _callPlatformToSendData(dataMap);//调用底层去向蓝牙设备发送消息
  }
  //对灯进行直接开关控制
  void _directControllerLight(bool isOpen,int type){
    Uint8List data = new Uint8List(4);
    data[0]=0xFE;
    data[1]=0xD1;
    data[2]=0x01;
    if(isOpen){//如果是开灯的话
      switch(type){
        case 1://如果是开冷灯
          data[3]=0x01;
          break;
        case 2://如果是开暖灯
          data[3]=0x02;
          break;
      }
    }else//如果是关灯的话
      data[3]=0x00;
    Map<String,Object> dataMap={"data":data};
    _callPlatformToSendData(dataMap);//调用底层去向蓝牙设备发送消息;//调用底层去向蓝牙设备发送消息
  }

  //灯pwm的slider改变时调用的函数
  void _pwmSliderChange(bool isCool){
    Uint8List data = new Uint8List(4);
    data[0]=0xFE;
    data[1]=isCool ? 0xD3 : 0xD4 ;
    data[2]=0x01;
    data[3]=isCool ? _coolLightShowPwm : _warmLightShowPwm;
    Map<String,Object> dataMap={"data":data};
    _callPlatformToSendData(dataMap);//调用底层去向蓝牙设备发送消息;//调用底层去向蓝牙设备发送消息
  }


  //显示时间的dataTimePicker
  void _showDatePicker(bool isAbsolute){
    MyPicker.showDateTimePicker(
        context: context,
        background: Colors.black,
        color: Colors.white,
        current: isAbsolute?_absoluteDateTime:null,
        relativeInitTime: isAbsolute?null:_relativeTimeRecode,
        isAbsolute: isAbsolute,
        magnification: 1.2,
        squeeze: 1.45,
        offAxisFraction: 0.2,
        onChange: isAbsolute?_absoluteTimePickerChange:null,
        onConfirm:isAbsolute?_absoluteTimePickerConfirm:null,
        onRelativeConfirm:isAbsolute?null:_relativeTimePickerConfirm
    );
  }

  //定时设置点击设置按钮后调用的函数
  void _timerSetting(bool isAbsolute){
    Uint8List data = new Uint8List(10);
    data[0]=0xFE;
    data[1]=isAbsolute ? 0xD8 : 0xD9;
    data[2]=0x07;
    data[3]=isAbsolute ? _absoluteDateTime.year-2000 : _relativeTimeRecode.relativeYear;
    data[4]=isAbsolute ? _absoluteDateTime.month : _relativeTimeRecode.relativeMonth;
    data[5]=isAbsolute ? _absoluteDateTime.day : _relativeTimeRecode.relativeDay;
    data[6]=isAbsolute ? _absoluteDateTime.hour : _relativeTimeRecode.relativeHour;
    data[7]=isAbsolute ? _absoluteDateTime.minute : _relativeTimeRecode.relativeMin;
    data[8]=isAbsolute ? _absoluteDateTime.second : _relativeTimeRecode.relativeSecond;
    data[9]=isAbsolute ? (_absoluteSwitchSelected ? 0x01 : 0x02) : (_relativeSwitchSelected ? 0x01 : 0x02);
    Map<String,Object> dataMap={"data":data};
    _callPlatformToSendData(dataMap);//调用底层去向蓝牙设备发送消息;//调用底层去向蓝牙设备发送消息
  }

  //绝对时间的timePicker修改时调用的函数
  void _absoluteTimePickerChange(DateTime dateTime){
      _absoluteDateTime = dateTime;
  }

  //绝对时间picker点击确认后调用的函数
  void _absoluteTimePickerConfirm(DateTime dateTime){
    _absoluteDateTime=dateTime;
    _absoluteDateStr=MyDate.format('yyyy-MM-dd HH:mm:ss', dateTime);
    _absoluteTimeTextController.text=_absoluteDateStr;
  }

  //相对时间picker点击确认后调用的函数
  void _relativeTimePickerConfirm({int year,int month,int day,int hour,int min,int second}){
    _relativeTimeRecode.relativeYear=year;
    _relativeTimeRecode.relativeMonth=month;
    _relativeTimeRecode.relativeDay=day;
    _relativeTimeRecode.relativeHour=hour;
    _relativeTimeRecode.relativeMin=min;
    _relativeTimeRecode.relativeSecond=second;
    _relativeDateStr=year.toString().padLeft(4, '0')+'-'+month.toString().padLeft(2, '0')+'-'+day.toString().padLeft(2, '0')+' '+hour.toString().padLeft(2, '0')+':'+min.toString().padLeft(2, '0')+':'+second.toString().padLeft(2, '0');
    _relativeTimeTextController.text=_relativeDateStr;
  }

  //显示toast
  void _showToast(String text){
    Toast.show(text, context, duration: Toast.LENGTH_SHORT, gravity:  Toast.BOTTOM);
  }

  //向底层操作系统发送消息去给蓝牙设备
  void _callPlatformToSendData(Map<String,Object> dataMap){
    dataMap["deviceName"]=DeviceName.LIGHT_DEVICE_NAME;
    dataMap["serviceUuid"]=defaultTargetPlatform==TargetPlatform.android?BlueUuid.androidLightServiceUuid:BlueUuid.iosLightServiceUuid;
    dataMap["writeUuid"]=defaultTargetPlatform==TargetPlatform.android?BlueUuid.androidLightWriteUuid:BlueUuid.iosLightWriteUuid;
    dataMap["notifyUuid"]=defaultTargetPlatform==TargetPlatform.android?BlueUuid.androidLightNotifyUuid:BlueUuid.iosLightNotifyUuid;
    dataMap["isWithResult"]=true;
    platform.invokeMethod('sendData',dataMap).then((result){});//调用底层去向蓝牙设备发送消息
  }

}

